import { In, Like, Not } from 'typeorm'
import bcrypt from 'bcrypt'
import jwt from 'jsonwebtoken'
import dayjs from 'dayjs'

import { datasource } from '../../db/index.js'

import userEntity from '../../model/userModel.js'
import roleModel from '../../model/roleModel.js'

import { isEmpty } from '#src/utils/index.js'

import { admin, initPassword } from '#src/config/account.js'

const userRepository = datasource.getRepository(userEntity)
const roleRepository = datasource.getRepository(roleModel)

// 生成/验证token 的秘钥
export const SECRET = 'abcdefg'

export const login = async (req, res) => {
  let { name, password } = req.body

  // 超管逻辑
  if (name === admin && password === initPassword) {
    let token = jwt.sign(
      {
        id: 0
      },
      SECRET
    )

    res.json({
      code: 1000,
      data: token,
      message: '登录成功'
    })

    return
  }

  let result = await userRepository.findOne({
    where: {
      name: name.trim()
    }
  })

  if (!result) {
    res.json({
      code: -1,
      data: null,
      message: '用户不存在,请先注册'
    })
    return
  }

  if (result.status === 0) {
    res.json({
      code: -1,
      data: null,
      message: '该用户帐号已禁用'
    })

    return
  }

  console.log('原始密码:', password)

  // 验证密码
  let compareResult = await bcrypt.compare(password.trim(), result.password)

  console.log('密码比较', compareResult)

  if (compareResult) {
    // 生成token
    console.log(result.userId, '用户id')
    // 签名
    let token = jwt.sign(
      {
        id: result.userId
      },
      SECRET
    )

    res.json({
      code: 1000,
      data: token,
      message: '登录成功'
    })
  } else {
    res.json({
      code: -1,
      data: null,
      message: '密码错误'
    })
  }
}

export const register = async (req, res) => {
  let { name, password } = req.body

  if (!name || !name.trim()) {
    res.json({
      code: -1,
      data: null,
      message: '用户名不能为空'
    })

    return
  }

  if (!password || !password.trim()) {
    res.json({
      code: -1,
      data: null,
      message: '密码不能为空'
    })

    return
  }

  let result = await userRepository.insert({
    name: name.trim(),
    password: password.trim()
  })

  console.log(result)

  res.send('注册成功')
}

/**
 * 登录接口-登录生成token后查询用户信息-前端未使用
 */

export const getUserInfoV2 = async (req, res) => {
  let authorization = req.headers.authorization

  // 从token里面拿到用户id

  if (!authorization) {
    res.status(401).end({
      code: -1,
      data: null,
      message: '未授权'
    })
    return
  }

  let token = authorization.split(' ')[1]

  try {
    let decoded = jwt.verify(token, SECRET)

    console.log('decoded 包含2个内容，一个是用户id， 一个是iat', decoded)
    let userId = decoded.id

    // 根据token里面的用户id查询到用户信息
    let userItem = await userRepository.findOne({
      where: {
        userId: userId
      }
    })

    res.send({
      data: userItem,
      code: 1000,
      message: '操作成功'
    })
  } catch (error) {
    console.log(error)
    res.json({
      code: -1,
      data: null,
      message: 'token错误'
    })
  }
}

/**
 * 用户详情-登录接口使用的
 */
export const getUserInfo = async (req, res) => {
  // console.log('authMiddleware 已经拿到了用户的id， 这里可以直接使用', req.userId)

  try {
    // 根据token里面的用户id查询到用户信息
    let userItem = await userRepository.findOne({
      where: {
        userId: req.userId
      },
      // 查询出用户的角色信息
      relations: ['roles']
    })

    if (!userItem) {
      res.json({
        code: -1,
        data: null,
        message: '用户信息不存在'
      })
      return
    }

    if (userItem.status === 0) {
      res.json({
        code: -1,
        data: null,
        message: '当前帐号已禁用'
      })
      return
    }

    delete userItem.password
    delete userItem.createTime
    delete userItem.updateTime
    delete userItem.status

    userItem.roles.map((p) => {
      return {
        roleId: p.roleId,
        roleName: p.roleName,
        desc: p.desc
      }
    })

    res.send({
      data: userItem,
      code: 1000,
      message: '操作成功'
    })
  } catch (error) {
    res.send({
      data: null,
      code: -1,
      message: '操作失败' + error.message
    })
  }
}

/**
 * 创建用户
 */
export const createUser = async (req, res) => {
  // 根据手机号查询是否存在账户
  try {
    let exitUser = await userRepository.findOne({
      where: {
        phone: req.body.phone
      }
    })

    if (exitUser) {
      res.json({
        code: -1,
        data: null,
        message: `手机号-${req.body.phone} 用户已存在`
      })
      return
    }

    let roleList = []

    // 验证角色id是否存在
    if (req.body.roleIds && req.body.roleIds.length) {
      // 根据角色Id查询出所有的角色
      roleList = await roleRepository.find({
        where: {
          roleId: In(req.body.roleIds)
        }
      })
    }

    let signPassword = await bcrypt.hash(initPassword, 10)
    console.log('初始化密码hash')
    console.log(signPassword)

    let result = await userRepository.save({
      name: req.body.name.trim(),
      email: req.body.email.trim(),
      phone: req.body.phone.trim(),
      roles: roleList,
      status: 1,
      password: signPassword
    })

    res.json({
      code: 1000,
      data: result,
      message: '操作成功'
    })
  } catch (error) {
    res.json({
      code: -1,
      data: null,
      message: '操作失败' + error.message
    })
  }
}

export const getMenuList = async (req, res) => {
  let userId = req.userId

  if (userId === undefined || userId === null) {
    res.json({
      code: 1000,
      data: [],
      message: '操作成功'
    })

    return
  }

  // 根据用户id - 查询到用户所拥有的角色以及角色对应的权限

  try {
    let result = await userRepository.findOne({
      where: {
        userId: userId
      },
      relations: ['roles', 'roles.permissions']
    })

    // 当前查询出来的权限，存在 人 对应多个角色，角色中包含多个权限， 权限有重复的数据
    let arr = []

    result.roles.forEach((p) => {
      arr = arr.concat(p.permissions)
    })

    res.json({
      code: 1000,
      data: {
        permissionList: arr,
        result
      },
      message: '操作成功'
    })
  } catch (error) {
    res.json({
      code: -1,
      data: null,
      message: error.message
    })
  }
}

/**
 * 用户详情-更新用户信息
 */
export const updateUser = async (req, res) => {
  const { roleIds } = req.body

  try {
    let roles = await roleRepository.find({
      where: {
        roleId: In(roleIds)
      }
    })

    // 手机号不能重复
    let exitPhone = await userRepository.createQueryBuilder('user')
    .where('user.phone =:phone', {
      phone: req.body.phone
    })
    .andWhere('user.userId <> :userId', {
      userId: req.body.userId
    })
    .andWhere('user.isDelete =:isDelete', {
      isDelete: 0
    })
    .getOne()

    if (exitPhone) {
      res.json({
        code: -1,
        data: null,
        message: `修改失败-手机号 ${req.body.phone}不能重复`
      })
      return
    }

    const userItem = await userRepository.findOne({
      where: {
        userId: req.body.userId
      }
    })

    userItem.name = req.body.name
    userItem.phone = req.body.phone
    userItem.email = req.body.email

    userItem.roles = roles

    await userRepository.save(userItem)

    res.json({
      code: 1000,
      data: null,
      message: '操作成功'
    })
  } catch (error) {
    res.json({
      code: -1,
      data: null,
      message: '操作失败' + error.message
    })
  }
}

/**
 * 分页查询用户信息
 */
export const getUserList = async (req, res) => {
  let { pageSize = 20, currentPage = 1, ...rest } = req.body

  let query = {}

  if (!isEmpty(rest.name)) {
    query.name = Like(`%${rest.name.trim()}%`)
  }

  if (!isEmpty(rest.phone)) {
    query.phone = Like(`%${rest.phone.trim()}%`)
  }

  if (!isEmpty(rest.status)) {
    query.status = rest.status
  }

  console.log(query)

  try {
    let result = await userRepository
      .createQueryBuilder('user')
      .where(query)
      .take(pageSize)
      .skip((currentPage - 1) * pageSize)
      .orderBy('updateTime', 'DESC')
      .getManyAndCount()

    if (result && result[0] && result[0].length) {
      result[0].forEach((p) => {
        delete p.password

        p.createTime = dayjs(p.createTime).format('YYYY-MM-DD HH:mm:ss')
        p.updateTime = dayjs(p.updateTime).format('YYYY-MM-DD HH:mm:ss')
      })
    }

    res.json({
      code: 1000,
      data: {
        list: result[0],
        total: result[1]
      },
      message: '操作成功'
    })
  } catch (error) {
    res.json({
      code: -1,
      data: null,
      message: '操作失败' + error.message
    })
  }
}

/**
 * 更新用户状态
 */
export const updateStatus = async (req, res) => {
  try {
    let userItem = await userRepository
      .createQueryBuilder('user')
      .where('user.userId = :userId', {
        userId: req.body.userId
      })
      .getOne()

    if (!userItem) {
      res.json({
        code: -1,
        data: null,
        message: '用户不存在'
      })
      return
    }

    userItem.status = userItem.status === 0 ? 1 : 0

    userItem.updateTime = dayjs().format('YYYY-MM-DD HH:mm:ss')

    await userRepository.save(userItem)

    res.json({
      code: 1000,
      data: null,
      message: '操作成功'
    })
  } catch (e) {
    res.json({
      code: -1,
      data: null,
      message: '操作失败' + e.message
    })
  }
}

/**
 * 重置密码
 */
export const resetPassword = async (req, res) => {
  let userId = req.body.userId

  if (Number(userId) === 0) {
    res.json({
      code: -1,
      data: null,
      message: '不允许初始化管理员帐号'
    })
    return
  }

  try {
    let row = await userRepository
      .createQueryBuilder('user')
      .where('user.userId =:userId', {
        userId
      })
      .getOne()

    if (!row) {
      res.json({
        code: -1,
        data: null,
        message: '操作失败, 用户不存在'
      })
      return
    }

    let signPassword = await bcrypt.hash(initPassword, 10)

    row.password = signPassword
    row.updateTime = dayjs().format('YYYY-MM-DD HH:mm:ss')

    await userRepository.save(row)

    res.json({
      code: 1000,
      data: null,
      message: '操作成功'
    })
  } catch (error) {
    console.log('【重置密码】-resetPassword')
    console.log(error)
    res.json({
      code: -1,
      data: null,
      message: '操作失败'
    })
  }
}

/**
 * 用户管理-查询用户详情
 */
export const getUserInfoById = async (req, res) => {
  try {
    let row = await userRepository
      .createQueryBuilder('user')
      .where('user.userId =:userId', {
        userId: req.query.userId
      })
      .leftJoinAndSelect('user.roles', 'roles')
      .getOne()

    if (!row) {
      res.json({
        code: -1,
        data: null,
        message: '角色不存在'
      })
      return
    }
    row.roleIds = []

    // 去掉不必要的字段
    // 普通用户挂载了角色
    if (row.roles.length) {
      row.roleIds = row.roles.map((p) => p.roleId)
      delete row.roles
    } else {
      // 超管或者用户没有挂载角色的情况
      delete row.roles
    }

    delete row.password

    res.json({
      code: 1000,
      data: row,
      message: '操作成功'
    })
  } catch (error) {
    res.json({
      code: -1,
      data: null,
      message: '操作失败' + error.message
    })
  }
}

/**
 * 删除用户
 */
export const deleteUserById = async (req, res) => {
  if (req.query.userId === req.userId) {
    // 要删除的用户跟当前token的用户是一样的，则删除的是自己帐号, 清空token
    // TODO: 从redis 中删除token
  }

  try {
    await userRepository
      .createQueryBuilder('user')
      .delete()
      .where('user.userId =:userId', {
        userId: req.query.userId
      })
      .execute()

    res.json({
      code: 1000,
      data: null,
      message: '操作成功'
    })
  } catch (error) {
    res.json({
      code: -1,
      data: null,
      message: '操作失败' + error.message
    })
  }
}
